Skip to content

Add Simplified Chinese localization to the admin panel - #981

Merged
sven-n merged 7 commits into
MUnique:masterfrom
Qinjianbo:contribution/admin-panel-zh-cn
Sep 29, 2026
Merged

sven-n merged 7 commits into
MUnique:masterfrom
Qinjianbo:contribution/admin-panel-zh-cn

Conversation

@Qinjianbo

@Qinjianbo Qinjianbo commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Administrators can select Simplified Chinese (zh-CN) for the admin panel,
configuration editor, and built-in plugin metadata. This adds 12 Chinese resource
sets and replaces remaining hard-coded UI captions with
resource-backed text.

The accompanying code preserves regional culture names during selection and
request localization, discovers deployed satellite cultures, resolves captions
for derived model types, and localizes shared forms, validation messages,
pagination, enum labels, configuration summaries, plugin configuration fields,
and update descriptions. English remains the neutral fallback. Authorization
roles, plugin identifiers, and command syntax keep their original values.

Database records, schema migrations, configuration initialization, and gameplay
values are outside this change. Names stored in configuration data may still
require separate translations.

Related to #379.

Validation

  • Full solution build passed on Linux with .NET 10: dotnet build src/MUnique.OpenMU.sln -c Release -p:ci=true --no-restore (0 errors; existing warnings remain).

  • Release build and Web test suite passed: 150 tests, 0 failures, 0 skipped.
    Command: dotnet test tests/MUnique.OpenMU.Web.Tests/MUnique.OpenMU.Web.Tests.csproj -c Release -p:ci=true --no-restore.
    Existing analyzer and dependency warnings remain.

  • XML/resource audit: all 12 Chinese resource sets parse, with no duplicate keys
    or placeholder mismatches in existing translations.

  • Localization tests exercise culture selection, enum round trips, model captions,
    plugin display resources, English fallback, translated placeholder consistency, and pagination behavior.

  • The implementation was also deployed locally for testing; the admin home,
    plugin, and chat command pages returned HTTP 200 with Chinese UI content.
    The isolated upstream branch excludes the local database-name completion work.

Review follow-up

Chinese translations are optional: resource checks validate placeholders only for
existing translations. A partial-resource regression test verifies that new
English-only keys fall back to English. Numbered display resource keys have been
replaced with type/member names, including nested configuration members; existing
English and Chinese text is unchanged. Extension-point key behavior and localized
model summaries in logs are now documented.

Validation after these changes: full Release solution build with -p:ci=true
passed (0 errors; existing warnings remain), and all 150 Web tests passed.

Merged upstream master at a0cfc0143 and resolved resource/party-caption conflicts, preserving upstream functionality and existing Chinese text. The validation above includes this merge.

@Qinjianbo
Qinjianbo marked this pull request as ready for review September 26, 2026 14:53
@Qinjianbo

Copy link
Copy Markdown
Contributor Author

Hi, this PR adds Simplified Chinese localization to the admin panel. The full solution builds successfully locally on Linux with .NET 10, all 116 Web tests pass, and Codacy checks pass.

The Azure Pipelines check fails, but I don’t have permission to access its logs. Could you please help check the failure details and let me know if any changes are needed?

Thank you for reviewing!

@sven-n sven-n left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this contribution, it's a big and careful piece of work!

Verification

  • Azure Pipelines failure is not caused by this PR. The MUnique.OpenMU check fails instantly (start == end) on other PRs too, including already merged ones (#973, #977, #978), so it's an infrastructure issue on our side.
  • I built the PR head and a test merge onto the current master (866b0f55, merges without conflicts) on Linux with .NET 10: dotnet build -c Release -p:ci=true → 0 errors.
  • All test projects pass (Tests 1033, Web.Tests 116, PlugIns 41, Network.Packets 602, Persistence.Initialization, AttributeSystem, ChatServer, Network, Pathfinding).

Looks good

  • ModelResourceProvider.GetModelResourceString walks base types, which fixes captions for the persistence-generated derived model types.
  • Switching the culture selector and RequestLocalizationOptions to culture.Name is needed for zh-CN. Existing de/en values still resolve, because neutral cultures keep the same name.
  • LocalizedPaginator subscribes to and unsubscribes from PaginationState correctly.
  • FieldCaption and EnumSelect now use DisplayAttribute.GetName(), which respects ResourceType.

Before merging

  1. TranslationCoverageTests.ChineseResourceSetsMatchNeutralKeysAndPlaceholders makes zh-CN mandatory for every new string. Every future PR that adds a key to one of the 12 neutral resource sets would fail CI unless it also adds a Chinese translation. No other language (e.g. de) has this requirement. Most contributors can't provide Chinese, so this would block unrelated work. Please keep the placeholder-consistency check (it's valuable), but only for keys that exist in zh-CN, and treat missing keys as fallback to English rather than a failure.

  2. Numbered resource keys like BotConfiguration_Display1_Name … _Display13_Name (about 55 in GameLogic/Properties/PlugInResources.resx, 5 in Persistence.Initialization) have no link to the property they describe. Reordering or inserting a property silently makes the keys misleading, and reviewers can't see from the key what text it holds. Please name them after the member, e.g. BotConfiguration_ResetBots_Name / _Description, the same way ModelResources already does ({Type}_{Property}_Caption).

Minor (non-blocking)

  • Update plugins (e.g. AddDuelConfigurationPlugIn) still keep PlugInName / PlugInDescription constants for the Name / Description overrides, while the [Display] text now lives in the resx. The English text is duplicated and can drift. Consider using the resource for both, or leaving the constants as the single source.
  • PlugInPointCaption uses the English name/description text itself as the resx key. Editing the text of a plug-in point attribute silently drops its translation. That's acceptable as a fallback, but worth a comment in the class.
  • Several ToString() overrides in DataModel are now culture-dependent. They also show up in server logs, so a server running under a non-English UI culture will log localized text. Probably fine, just be aware.

Happy to merge once 1 and 2 are addressed. 🙂


Generated by Claude Code

@Qinjianbo

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review, @sven-n! Both pre-merge requests are now addressed:

  1. Chinese translations are optional. The resource test checks placeholder consistency only for keys with an existing Chinese translation. A regression test verifies that an English-only key falls back to English without requiring a Chinese entry.
  2. The 55 numbered display resource key groups have been renamed using their actual type/member names, including nested configuration classes. The existing English and Chinese text is unchanged by the renaming.

I also documented the English-text key behavior in PlugInPointCaption and noted that localized model summaries can appear in server logs.

The branch now includes upstream master at a0cfc0143, with the resource and party-caption conflicts resolved. Validation of the updated branch (855e1734d) on Linux with .NET 10:

  • Full Release solution build with -p:ci=true: 0 errors (existing warnings remain).
  • Web test suite: all 150 tests passed.

The local database-name translation work remains outside this PR. Could you please take another look when you have time? Thank you!

@sven-n sven-n left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick follow-up, @Qinjianbo! Re-review of dd99166f:

Both pre-merge points are resolved

  1. ExistingChineseResourcesMatchNeutralPlaceholders now checks placeholders only for keys that have a Chinese translation and skips missing ones. The new MissingChineseKeyFallsBackToEnglish test with FallbackResources covers the fallback. Future PRs no longer need to add zh-CN text.
  2. No numbered _DisplayN_ keys are left. All keys now follow {Type}_{Member}_Name/Description.

The minor points were also handled: the key behavior is documented in PlugInPointCaption.

Merge resolution (855e1734): I checked it with a remerge diff. Both sides of the resource conflicts were kept, including the upstream Raklion, guild-role and guild-page keys, and PartyBadge now uses upstream's PartyBadgeTitle. Nothing was lost.

Verification: I test-merged onto the current master (4348ecae) with no conflicts. On .NET 10:

  • dotnet build -c Release -p:ci=true: 0 errors.
  • All test projects pass: Tests 1120, Web.Tests 150, Network.Packets 608, Persistence.Initialization 32 (6 skipped), Network 73 (4 skipped), PlugIns 41, AttributeSystem 44, ChatServer 26, Pathfinding 10.

The failing Azure MUnique.OpenMU check is our infrastructure issue. It also fails instantly on other PRs, including merged ones, so it isn't caused by this PR. Codacy is green.

LGTM, merging. 🎉


Generated by Claude Code

@sven-n
sven-n merged commit 2b70acc into MUnique:master Sep 29, 2026
1 of 2 checks passed
Qinjianbo added a commit to Qinjianbo/OpenMU that referenced this pull request Sep 30, 2026
Merge upstream/master at ff14409, including merged PR MUnique#981. Reserve versions 100116–100133 for fork translation updates and migrate recognized legacy update records before discovery so upstream updates remain available. Match serializer test fixtures by neutral item and set names.

Validation: full solution Release build passed; initialization 71 passed / 6 skipped; Web 166 passed; packets 611 passed; attributes 48 passed. Main suite had 1210 passed and 16 fixture lookup failures; all 18 serializer cases passed after fixing the five neutral-name lookups.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants